using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace RapidHDL
{
    public partial class ChipConsole : UserControl
    {
        RapidHardware RapidHardware;
        const string IO_TEST_SOURCE = "io_test_source";
        const string IO_TEST_VIEW = ".io_test";

        public ChipConsole()
        {
            InitializeComponent();
        }

        public void AttachRapidHardware(RapidHardware poRapidHardware)
        {
            RapidHardware = poRapidHardware;
            RapidHardware.RapidHardwareEvent += new RapidHardware.RapidHardwareEventDelegate(this.RapidHardwareEvent);
        }

        public void ShowTranscript()
        {
            SetConsoleText(RapidHardware.Transcript.GetTranscript());
        }

        private void IOTest()
        {
            SignalSource oSource = RapidHardware.SystemInterface.GetSignalSource(IO_TEST_SOURCE);
            SignalView oView = RapidHardware.SystemInterface.GetSignalView(IO_TEST_VIEW);
            oSource.ValueAsInt = 55;
            if (oView.ValueAsInt != 55)
            {
                RapidHardware.Transcript.AddTranscript("IO Test Failed - 55");
                return;
            }
            oSource.ValueAsInt = 0;
            if (oView.ValueAsInt != 0)
            {
                RapidHardware.Transcript.AddTranscript("IO Test Failed - 0");
                return;
            }
            oSource.ValueAsInt = 10;
            if (oView.ValueAsInt != 10)
            {
                RapidHardware.Transcript.AddTranscript("IO Test Failed - 10");
                return;
            }
            RapidHardware.Transcript.AddTranscript("STARTUP IO Test Complete");
            //RapidHardware.SystemInterface.BenchmarkIO(1, 5,true);
        }

        private void ChipConsole_Resize(object sender, EventArgs e)
        {
            const int GAP = 10;

            txtInput.Top = this.Height - txtInput.Height - GAP;
            lblInstruction.Top = txtInput.Top;
            txtConsole.Top = 0;
            txtConsole.Left = 0;
            txtConsole.Width = this.Width;
            txtConsole.Height = txtInput.Top - GAP;

        }

        private void SetConsoleText(string psInput)
        {
            string sInput = psInput.Replace("\r\n", "\n");
            sInput = sInput.Replace("\n", "\r\n");
            txtConsole.Text = sInput;
            txtConsole.SelectionStart = txtConsole.Text.Length;
            txtConsole.ScrollToCaret();
        }

        private void txtInput_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue != 13)         
                return;

            txtInput.Text = txtInput.Text.Trim().ToLower();
            string sResult = ProcessInput(txtInput.Text);
            SetConsoleText(sResult);
            txtInput.Text = "";
        }

        private string CommandFail(string psError, string psInput)
        {
            string sMessage = "Error -> '" + psInput + "'\n" + psError;
            sMessage += "Detail -> " + psError;
            RapidHardware.Transcript.AddTranscript(sMessage);
            return sMessage;
        }

        private string CommandSuccess(string sValue)
        {
            RapidHardware.Transcript.AddTranscript(sValue);
            RapidHardware.SubmitHardwareEvent(RapidHardwareEventTypes.AfterHardwareExecute, sValue, null);
            return DisplayInterface() + "\n\n" + sValue;
        }

        bool RapidHardwareEvent(RapidHardware poRapidHardware, RapidHardwareEventTypes pEventType, object oParam1, object oParam2)
        {
            switch (pEventType)
            {
                case RapidHardwareEventTypes.HardwareStarted:
                    IOTest();
                    ShowTranscript();
                    break;
                default:
                    break;
            }
            return true;
        }

        private string ProcessInput(string psInput)
        {
            string sInput = psInput.Replace("  "," ").Replace("  "," ").Replace("  "," ").Replace("  "," ");

            string[] saCommand = sInput.Split(' ');
            if (saCommand.Length == 0)
                return CommandFail("Invalid Input",sInput);

            switch (saCommand[0])
            {
                case "g":
                    if (saCommand.Length < 2)
                        return CommandFail("No Clock Cycles Given",sInput);
                    if (!Conversion.IsNumeric(saCommand[1]))
                        return CommandFail("Invalid Clock Cycles",sInput);
                    int iClockCycles = Conversion.StringToInt(saCommand[1]);
                    RapidHardware.SystemInterface.SystemControl.Go(iClockCycles);
                    return CommandSuccess("Clock(" + iClockCycles.ToString() + ") - " + RapidHardware.FPGAInterface.ClockCycles.ToString());
                case "r":
                    RapidHardware.SystemInterface.SystemControl.Reset();
                    return CommandSuccess("Reset");
                case "d":
                    return DisplayInterface();
                case "t":
                    return RapidHardware.Transcript.GetTranscript();
                default:
                    return CommandFail("Invalid Input",sInput);                
            }
        }

        private string DisplayInterface()
        {
            bool bOdd = true;
            string sResult = "Inputs:";
            foreach (SignalSource oSignal in RapidHardware.SystemInterface.SignalSources.Values)
            {
                if (bOdd)
                {
                    sResult += "\n  ";
                }
                else
                {
                    sResult += "   ";
                }
                bOdd = !bOdd;
                sResult += oSignal.Name.PadRight(25, ' ') + oSignal.ValueAsString.PadLeft(14, ' ') + " " + oSignal.ValueAsInt.ToString().PadLeft(6, ' ');
            }
            sResult += "\n\nViews:";
            bOdd = true;
            foreach (SignalView oSignal in RapidHardware.SystemInterface.SignalViews.Values)
            {
                if (bOdd)
                {
                    sResult += "\n  ";
                }
                else
                {
                    sResult += "   ";
                }
                bOdd = !bOdd;
                sResult += oSignal.Name.PadRight(25, ' ') + oSignal.ValueAsString.PadLeft(14, ' ') + " " + oSignal.ValueAsInt.ToString().PadLeft(6, ' ');
            }

            return sResult;
        }

        private void txtInput_TextChanged(object sender, EventArgs e)
        {

        }

        private void ChipConsole_Load(object sender, EventArgs e)
        {

        }

    }
}
